#pragma once
#include "epoller.hpp"
#include "connection.hpp"
#include <unordered_map>

//1、对就绪事件进行通知
//2、对连接进行管理
class Reactor
{
    static const int gnum=64;
public:
    Reactor()
    {}

    void AddConnection(int fd,uint32_t events,func_t recv,func_t send,func_t excepeter)
    {
        //1、构建Connection对象
        Connection* conn=new Connection(fd);
        conn->SetEvents(events);
        conn->Register(recv,send,excepeter);
        conn->SetSelf(this);
        //2、向内核中设定对fd的关心
        _epoller.AddEvent(conn->SockFd(),conn->Events());
        //3、向集合当中添加Connection对象
        _connections.insert(std::make_pair(conn->SockFd(),conn));
    }

    bool ConnectionIsExists(int sockfd)
    {
        std::unordered_map<int,Connection*>::iterator it=_connections.find(sockfd);
        return it!=_connections.end();
    }

    void LoopOnce(int timeout)
    {
        int n=_epoller.Wait(revs,gnum,timeout);
            for(int i=0;i<n;i++)
            {
                int sockfd=revs[i].data.fd; 
                uint32_t revents=revs[i].events;
                //出现问题在读写时处理
                if(revents&EPOLLHUP)//对方把连接关了
                {
                    revents|=(EPOLLIN|EPOLLOUT);
                }
                if(revents&EPOLLERR)//出错
                {
                    revents|=(EPOLLIN|EPOLLOUT);
                }
                if(revents&EPOLLIN)
                {
                    if((ConnectionIsExists(sockfd))&&(_connections[sockfd]->_recver!=nullptr))
                    {
                        _connections[sockfd]->_recver(_connections[sockfd]);
                    }
                }
                if(revents&EPOLLOUT)
                {
                    if((ConnectionIsExists(sockfd))&&(_connections[sockfd]->_sender!=nullptr))
                    {
                        _connections[sockfd]->_sender(_connections[sockfd]);
                    }
                }
            }
    }
    //事件派发
    void Dispatcher()
    {
        int timeout=-1;
        while(true)
        {
            LoopOnce(timeout);
        }
    }

private:
    std::unordered_map<int,Connection*> _connections; //int -> sockfd
    Epoller _epoller;
    struct epoll_event revs[gnum];//就绪事件的数组
};